use std::path::{Path, PathBuf};
use anyhow::Result;
use log::{info, warn, error};
use std::env;

use crate::errors::{ConversionError, ConversionWarnings, ResultExt};
use crate::project::Project;
use crate::project_parser::ProjectParser;
use crate::cmake_generator::{CMakeProject, generate_root_cmake};
use crate::sln_parser::parse_solution;
use crate::file_copier::FileCopier;
use crate::progress::ConversionProgress;
use crate::cpp_properties_generator;
use crate::clangd_generator;

/// 管理项目转换流程的核心模块
pub struct ConversionManager {
    input_dir: PathBuf,
    output_dir: PathBuf,
    qt_dir: Option<String>,
    warnings: ConversionWarnings,
    progress: Option<ConversionProgress>,
    show_progress: bool,
    generate_cpp_properties: bool,
    generate_clangd: bool,
    clangd_template: Option<PathBuf>,
    parsed_projects: Vec<Project>,
    solution_dir: Option<PathBuf>,  // 添加解决方案目录字段
}

impl ConversionManager {
    /// 创建新的转换管理器实例
    pub fn new(input_dir: &Path, output_dir: &Path, qt_dir: Option<String>) -> Result<Self> {
        // 确保输入目录存在
        if !input_dir.exists() || !input_dir.is_dir() {
            return Err(ConversionError::Other(format!(
                "输入目录不存在: {}",
                input_dir.display()
            )).into());
        }
        
        // 创建输出目录（如果不存在）
        if !output_dir.exists() {
            info!("创建输出目录: {}", output_dir.display());
            std::fs::create_dir_all(output_dir)
                .with_context(|| format!("无法创建输出目录: {}", output_dir.display()))?;
        }
        
        // 尝试查找默认的clangd模板文件
        let mut clangd_template = None;
        // 首先检查相对于当前工作目录的路径
        let cwd_template_path = PathBuf::from("./config/clangd_template.yaml");
        if cwd_template_path.exists() {
            info!("找到默认clangd模板文件: {}", cwd_template_path.display());
            clangd_template = Some(cwd_template_path);
        } else {
            // 然后检查相对于可执行文件目录的路径
            if let Ok(exe_path) = env::current_exe() {
                if let Some(exe_dir) = exe_path.parent() {
                    let exe_template_path = exe_dir.join("config/clangd_template.yaml");
                    if exe_template_path.exists() {
                        info!("找到默认clangd模板文件: {}", exe_template_path.display());
                        clangd_template = Some(exe_template_path);
                    }
                }
            }
        }
        
        Ok(ConversionManager {
            input_dir: input_dir.to_path_buf(),
            output_dir: output_dir.to_path_buf(),
            qt_dir,
            warnings: ConversionWarnings::new(),
            progress: None,
            show_progress: false,
            generate_cpp_properties: false,
            generate_clangd: false,
            clangd_template,
            parsed_projects: Vec::new(),
            solution_dir: None,  // 初始化为None
        })
    }
      /// 设置是否显示进度条
    pub fn with_progress(mut self, show_progress: bool) -> Self {
        self.show_progress = show_progress;
        if show_progress {
            self.progress = Some(ConversionProgress::new());
        }
        self
    }
    
    /// 设置是否生成c_cpp_properties.json文件
    pub fn with_cpp_properties(mut self, generate_cpp_properties: bool) -> Self {
        self.generate_cpp_properties = generate_cpp_properties;
        self
    }
    
    /// 设置是否生成.clangd配置文件
    pub fn with_clangd(mut self, generate_clangd: bool) -> Self {
        self.generate_clangd = generate_clangd;
        self
    }
    
    /// 设置clangd配置模板文件路径
    pub fn with_clangd_template(mut self, clangd_template: &Path) -> Self {
        // 显式指定的模板路径总是优先于默认模板
        info!("使用用户指定的clangd模板文件: {}", clangd_template.display());
        self.clangd_template = Some(clangd_template.to_path_buf());
        self
    }
    
    /// 获取转换过程中的警告
    pub fn get_warnings(&self) -> &ConversionWarnings {
        &self.warnings
    }
    
    /// 执行转换流程
    pub fn convert(&mut self) -> Result<()> {
        info!("开始转换流程");
        info!("输入目录: {}", self.input_dir.display());
        info!("输出目录: {}", self.output_dir.display());
        
        // 创建文件复制器
        let mut file_copier = FileCopier::new(&self.input_dir);
        
        // 查找所有解决方案(.sln)文件
        let solution_files = file_copier.find_files(&self.input_dir, ".sln");
        info!("找到 {} 个解决方案文件", solution_files.len());
        
        // 如果没有找到解决方案文件，尝试查找项目文件
        let project_files = if solution_files.is_empty() {
            file_copier.find_files(&self.input_dir, ".vcxproj")
        } else {
            Vec::new()
        };
        
        if solution_files.is_empty() && project_files.is_empty() {
            return Err(ConversionError::Other("未找到Visual Studio解决方案或项目文件".to_string()).into());
        }
        
        // 初始化进度条
        if let Some(progress) = &mut self.progress {
            if !solution_files.is_empty() {
                progress.init_solution_progress(solution_files.len() as u64);
            }
            
            let total_projects = if !solution_files.is_empty() {
                // 估计项目数量：假设每个解决方案平均有5个项目
                solution_files.len() as u64 * 5
            } else {
                project_files.len() as u64
            };
            
            progress.init_project_progress(total_projects);
            
            // 粗略估计文件数量：每个项目平均20个文件
            let estimated_files = total_projects * 20;
            progress.init_file_progress(estimated_files);
        }
        
        if !solution_files.is_empty() {
            // 处理解决方案文件
            for solution_file in &solution_files {
                let solution_name = solution_file
                    .file_stem()
                    .unwrap_or_default()
                    .to_string_lossy()
                    .to_string();
                
                if let Some(progress) = &mut self.progress {
                    progress.set_solution(&solution_name);
                }
                
                match self.convert_solution(solution_file, &mut file_copier) {
                    Ok(_) => {
                        info!("解决方案 {} 转换成功", solution_file.display());
                        if let Some(progress) = &self.progress {
                            progress.inc_solution();
                        }
                    },
                    Err(err) => {
                        let error_msg = format!("{}", err);
                        error!("解决方案 {} 转换失败: {}", solution_file.display(), error_msg);
                        self.warnings.add_ignored_setting(format!("解决方案 {} 转换失败", solution_file.display()));
                        
                        if let Some(progress) = &self.progress {
                            progress.solution_failed(&solution_name, &error_msg);
                            progress.inc_solution();
                        }
                    }
                }
            }
        } else {
            // 处理单独的项目文件
            for project_file in &project_files {
                let project_name = project_file
                    .file_stem()
                    .unwrap_or_default()
                    .to_string_lossy()
                    .to_string();
                
                if let Some(progress) = &mut self.progress {
                    progress.set_project(&project_name);
                }
                
                match self.convert_project(project_file, &mut file_copier) {
                    Ok(_) => {
                        info!("项目 {} 转换成功", project_file.display());
                        if let Some(progress) = &self.progress {
                            progress.project_success(&project_name);
                            progress.inc_project();
                        }
                    },
                    Err(err) => {
                        let error_msg = format!("{}", err);
                        error!("项目 {} 转换失败: {}", project_file.display(), error_msg);
                        self.warnings.add_ignored_setting(format!("项目 {} 转换失败", project_file.display()));
                        
                        if let Some(progress) = &self.progress {
                            progress.project_failed(&project_name, &error_msg);
                            progress.inc_project();
                        }
                    }
                }
            }
        }
        
        // 合并文件复制器中的警告
        merge_warnings(&mut self.warnings, file_copier.get_warnings());
          // 完成所有进度
        if let Some(progress) = &self.progress {
            progress.finish();
        }
        
        // 生成c_cpp_properties.json文件（如果需要）
        if self.generate_cpp_properties {
            if let Err(e) = self.generate_cpp_properties_file() {
                warn!("生成 c_cpp_properties.json 失败: {}", e);
                self.warnings.add_ignored_setting("无法生成 c_cpp_properties.json 文件".to_string());
            }
        }
        
        // 生成.clangd配置文件（如果需要）
        if self.generate_clangd {
            if let Err(e) = self.generate_clangd_file() {
                warn!("生成 .clangd 配置文件失败: {}", e);
                self.warnings.add_ignored_setting("无法生成 .clangd 配置文件".to_string());
            }
        }
        
        // 报告转换结果
        if self.warnings.has_warnings() {
            info!("转换流程完成，但有警告");
            info!("缺失文件: {}", self.warnings.missing_files.len());
            info!("忽略设置: {}", self.warnings.ignored_settings.len());
            info!("路径问题: {}", self.warnings.path_issues.len());
        } else {
            info!("转换流程完全成功完成，无警告");
        }
        
        Ok(())
    }
    
    /// 将Visual Studio解决方案转换为CMake
    fn convert_solution(&mut self, solution_path: &Path, file_copier: &mut FileCopier) -> Result<()> {
        info!("转换解决方案: {}", solution_path.display());
        
        // 使用sln_parser模块解析解决方案文件
        let solution = parse_solution(solution_path)
            .with_context(|| format!("解析解决方案文件 {} 失败", solution_path.display()))?;
          // 创建解决方案输出目录
        let solution_dir = self.output_dir.join(solution.solution_name.clone());
        std::fs::create_dir_all(&solution_dir)
            .with_context(|| format!("创建解决方案输出目录 {} 失败", solution_dir.display()))?;
        
        // 保存解决方案目录以供后续使用
        self.solution_dir = Some(solution_dir.clone());
        
        // 更新项目进度条
        if let Some(progress) = &mut self.progress {
            // 更新项目进度条以反映实际项目数量
            if let Some(pb) = &progress.project_progress {
                pb.set_length(solution.projects.len() as u64);
            }
        }
        
        // 跟踪成功的项目，用于最终的CMakeLists.txt
        let mut successful_projects = Vec::new();
        
        // 先解析所有项目以获取它们的详细信息
        let mut parsed_projects = Vec::new();
        for project in &solution.projects {
            info!("解析项目: {}", project.name);
            
            if let Some(progress) = &mut self.progress {
                progress.set_project(&project.name);
            }
              if project._path.exists() {
                // 使用ProjectParser解析项目文件
                let rust_project = Project::new(project.name.clone());
                let mut parser = ProjectParser::new(rust_project);                match parser.parse_vcxproj(&project._path) {
                    Ok(_) => {
                        info!("项目解析成功: {}", project.name);
                        // 存储到本地变量用于CMake生成
                        parsed_projects.push((project.name.clone(), project._path.clone(), parser.project.clone()));
                        // 存储到结构体字段用于c_cpp_properties.json生成
                        self.parsed_projects.push(parser.project);
                    },
                    Err(err) => {
                        error!("解析项目 {} 失败: {}", project.name, err);
                        self.warnings.add_ignored_setting(format!("项目 {} 解析失败: {}", project.name, err));
                        
                        if let Some(progress) = &self.progress {
                            progress.project_failed(&project.name, &format!("解析失败: {}", err));
                        }
                    }
                }            } else {
                warn!("项目文件未找到: {}", project._path.display());
                self.warnings.add_missing_file(project._path.clone());
                
                if let Some(progress) = &self.progress {
                    progress.project_failed(&project.name, "项目文件未找到");
                }
            }
            
            if let Some(progress) = &self.progress {
                progress.inc_project();
            }
        }
        
        // 更新文件进度条
        if let Some(progress) = &mut self.progress {
            // 预计文件数：每个项目的源文件+头文件+资源+表单
            let mut total_files = 0;
            for (_, _, project) in &parsed_projects {
                total_files += project.source_files.len() + 
                             project.header_files.len() + 
                             project.resources.len() + 
                             project.forms.len();
            }
            
            // 更新文件进度条以反映实际文件数量
            if let Some(pb) = &progress.file_progress {
                pb.set_length(total_files as u64);
            }
        }
        
        // 现在为每个项目生成CMake文件
        for (project_name, project_path, rust_project) in parsed_projects {
            info!("为项目生成CMake: {}", project_name);
            
            // 创建项目输出目录（作为解决方案的子目录）
            let project_dir = solution_dir.join(&project_name);
            
            // 将项目转换为CMake
            let cmake_result = CMakeProject::from_project(
                &rust_project, 
                &project_path, 
                &solution_dir, 
                self.qt_dir.clone()
            );
            
            match cmake_result {
                Ok(cmake_project) => {
                    // 先复制源文件
                    let file_count = rust_project.source_files.len() + 
                                     rust_project.header_files.len() + 
                                     rust_project.resources.len() + 
                                     rust_project.forms.len();
                                     
                    if let Err(err) = file_copier.copy_project_files(&rust_project, &project_dir) {
                        error!("为项目 {} 复制源文件失败: {}", project_name, err);
                        self.warnings.add_ignored_setting(format!(
                            "项目 {} 的文件复制失败: {}", project_name, err
                        ));
                        
                        if let Some(progress) = &self.progress {
                            progress.project_failed(&project_name, &format!("文件复制失败: {}", err));
                            progress.inc_files(file_count as u64); // 跳过所有文件
                        }
                    } else {
                        // 更新文件进度
                        if let Some(progress) = &self.progress {
                            progress.inc_files(file_count as u64);
                        }
                        
                        // 然后生成CMake文件
                        if let Err(err) = cmake_project.generate_cmake_file() {
                            error!("为项目 {} 生成CMake失败: {}", project_name, err);
                            self.warnings.add_ignored_setting(format!(
                                "项目 {} 的CMake生成失败: {}", project_name, err
                            ));
                            
                            if let Some(progress) = &self.progress {
                                progress.project_failed(&project_name, &format!("CMake生成失败: {}", err));
                            }                        } else {
                            successful_projects.push(project_name.clone());
                            info!("成功为项目生成CMake: {}", project_name);
                            
                            if let Some(progress) = &self.progress {
                                progress.project_success(&project_name);
                            }
                        }
                    }
                },
                Err(err) => {
                    error!("将项目 {} 转换为CMake失败: {}", project_name, err);
                    self.warnings.add_ignored_setting(format!(
                        "项目 {} 的CMake对象创建失败: {}", project_name, err
                    ));
                    
                    if let Some(progress) = &self.progress {
                        progress.project_failed(&project_name, &format!("CMake对象创建失败: {}", err));
                    }
                }
            }
        }
        
        // 为解决方案生成根CMakeLists.txt，仅包含成功的项目
        if !successful_projects.is_empty() {
            // 创建一个只包含成功项目的解决方案
            let mut filtered_solution = solution.clone();
            filtered_solution.projects.retain(|p| successful_projects.contains(&p.name));
            
            if let Err(err) = generate_root_cmake(&filtered_solution, &solution_dir) {
                error!("生成根CMakeLists.txt失败: {}", err);
                self.warnings.add_ignored_setting("根CMakeLists.txt生成失败".to_string());
            } else {
                info!("为解决方案生成了包含 {} 个项目的根CMakeLists.txt", successful_projects.len());
            }
        } else {
            warn!("没有项目成功转换，跳过根CMakeLists.txt生成");
            self.warnings.add_ignored_setting("没有成功的项目用于生成根CMakeLists.txt".to_string());
        }
        
        info!("解决方案转换完成: {}", solution.solution_name);
        Ok(())
    }
    
    /// 将单个Visual Studio项目转换为CMake
    fn convert_project(&mut self, project_path: &Path, file_copier: &mut FileCopier) -> Result<()> {
        info!("转换独立项目: {}", project_path.display());
        
        // 使用ProjectParser解析项目文件
        let project_name = project_path.file_stem()
            .unwrap_or_default()
            .to_string_lossy()
            .to_string();
            
        let rust_project = Project::new(project_name);
        let mut parser = ProjectParser::new(rust_project);
          parser.parse_vcxproj(project_path)
            .with_context(|| format!("解析项目文件 {} 失败", project_path.display()))?;
        
        // 存储已解析的项目用于c_cpp_properties.json生成
        self.parsed_projects.push(parser.project.clone());
        
        // 创建项目输出目录
        let project_dir = self.output_dir.clone();
        
        // 更新文件进度条
        if let Some(progress) = &mut self.progress {
            let file_count = parser.project.source_files.len() + 
                           parser.project.header_files.len() + 
                           parser.project.resources.len() + 
                           parser.project.forms.len();
                           
            if let Some(pb) = &progress.file_progress {
                pb.set_length(file_count as u64);
            }
        }
        
        // 将源文件复制到输出目录
        let file_copy_result = file_copier.copy_project_files(&parser.project, &project_dir);
        
        // 更新文件进度
        if let Some(progress) = &self.progress {
            let file_count = parser.project.source_files.len() + 
                           parser.project.header_files.len() + 
                           parser.project.resources.len() + 
                           parser.project.forms.len();
                           
            progress.inc_files(file_count as u64);
        }
        
        // 检查文件复制结果
        file_copy_result.with_context(|| format!("复制项目 {} 的文件失败", parser.project.name))?;
        
        // 将项目转换为CMake
        let cmake_project = CMakeProject::from_project(
            &parser.project, 
            project_path, 
            &project_dir, 
            self.qt_dir.clone()
        ).with_context(|| format!("创建项目 {} 的CMake对象失败", parser.project.name))?;
        
        cmake_project.generate_cmake_file()
            .with_context(|| format!("生成项目 {} 的CMake文件失败", parser.project.name))?;
          info!("项目转换完成: {}", parser.project.name);
        Ok(())
    }    /// 生成VS Code C/C++插件的c_cpp_properties.json配置文件
    fn generate_cpp_properties_file(&self) -> Result<()> {
        info!("生成 c_cpp_properties.json 配置文件");
        
        // 转换为引用向量，以匹配from_projects方法的签名
        let project_refs: Vec<&Project> = self.parsed_projects.iter().collect();
        
        let config = cpp_properties_generator::CppPropertiesConfig::from_projects(
            &project_refs,
            self.qt_dir.as_ref()
        );
        
        // 使用解决方案目录（如果存在）或输出目录作为fallback
        let target_dir = self.solution_dir.as_ref().unwrap_or(&self.output_dir);
        
        // 生成配置文件
        config.generate_json_file(target_dir)?;
        
        info!("c_cpp_properties.json 生成完成");
        Ok(())
    }
    
    /// 生成clangd配置文件(.clangd)
    fn generate_clangd_file(&self) -> Result<()> {
        info!("生成 .clangd 配置文件");
        
        // 转换为引用向量，以匹配from_projects方法的签名
        let project_refs: Vec<&Project> = self.parsed_projects.iter().collect();
        
        let mut config = clangd_generator::ClangdConfig::from_projects(
            &project_refs,
            self.qt_dir.as_ref()
        );
        
        // 如果有指定的模板文件，从模板加载自定义配置
        if let Some(template_path) = &self.clangd_template {
            info!("从模板文件加载clangd配置: {}", template_path.display());
            if let Err(e) = config.load_template(template_path) {
                warn!("加载clangd模板文件失败: {}", e);
                warn!("将使用默认clangd配置");
            } else {
                info!("成功加载clangd模板配置");
            }
        } else {
            info!("未指定clangd模板文件，使用默认配置");
        }
        
        // 使用解决方案目录（如果存在）或输出目录作为fallback
        let target_dir = self.solution_dir.as_ref().unwrap_or(&self.output_dir);
        
        // 生成配置文件
        config.generate_clangd_file(target_dir)?;
        
        info!(".clangd 生成完成");
        Ok(())
    }
}

/// 合并两个警告对象
fn merge_warnings(target: &mut ConversionWarnings, source: &ConversionWarnings) {
    // 合并缺失文件
    for missing_file in &source.missing_files {
        if !target.missing_files.contains(missing_file) {
            target.missing_files.push(missing_file.clone());
        }
    }
    
    // 合并忽略设置
    for ignored_setting in &source.ignored_settings {
        if !target.ignored_settings.contains(ignored_setting) {
            target.ignored_settings.push(ignored_setting.clone());
        }
    }
    
    // 合并路径问题
    for path_issue in &source.path_issues {
        if !target.path_issues.contains(path_issue) {
            target.path_issues.push(path_issue.clone());
        }
    }
}

#[cfg(test)]
mod tests {    use super::*;
    use std::fs;

    #[test]
    fn test_new_conversion_manager() {
        // 使用系统临时目录
        let temp_dir = std::env::temp_dir();
        let input_dir = temp_dir.join("vs2cmake_test_input");
        let output_dir = temp_dir.join("vs2cmake_test_output");
        
        // 确保测试目录存在
        if !input_dir.exists() {
            fs::create_dir_all(&input_dir).unwrap();
        }
        
        // 清理上一次测试的输出目录（如果存在）
        if output_dir.exists() {
            fs::remove_dir_all(&output_dir).unwrap_or(());
        }
        
        let result = ConversionManager::new(&input_dir, &output_dir, None);
        assert!(result.is_ok());
        assert!(output_dir.exists());
        
        // 清理测试目录
        fs::remove_dir_all(&input_dir).unwrap_or(());
        fs::remove_dir_all(&output_dir).unwrap_or(());
    }
} 